package chances.wechat.msggw.impl;

import java.io.IOException;
import java.rmi.RemoteException;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;

import chances.utils.JsonUtils;
import chances.wechat.msggw.context.BaseContext;
import chances.wechat.msggw.resp.BaseResponse;
import chances.wechat.utils.HTTPPoster;
import okhttp3.Call;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

import com.fasterxml.jackson.core.JsonParser;

public class BaseService {

    public static final MediaType JSON = MediaType
            .parse("application/json; charset=utf-8");

    @Value("${okhttp3.connect.timeout:5}")
    private int connectTimeOut;

    @Value("${okhttp3.read.timeout:10}")
    private int readTimeOut;

    // @Autowired
    // GwConfig config;

    static Logger errLog = LoggerFactory.getLogger("errorLogger");

    static Logger logger = LoggerFactory.getLogger("remoteCallLogger");

    protected <T> T doPost(BaseContext msgContext, String url, String body,
            Class<T> clazz) throws RemoteException {
        msgContext.setUrl(url);
        msgContext.setBody(body);
        logger.debug("{}\r\n{}", url, body);
        try {
            String response = HTTPPoster.post(url, body);
            logger.debug("{}\r\n{}", url, response);
            T result = (T) parse(response, clazz);
            ((BaseResponse) result).setContent(response);
            return result;
        } catch (IOException e) {
            errLog.error(e.getMessage(), e);
            throw new RemoteException(e.getMessage(), e);
        }
    }

    protected <T> T doNewPost(BaseContext msgContext, String url,
            Class<T> clazz) throws RemoteException {
        try {
            String response = postMethod(url, msgContext);
            logger.debug("{}\r\n{}", url, response);
            T result = (T) parse(response, clazz);
            ((BaseResponse) result).setContent(response);
            return result;
        } catch (IOException e) {
            errLog.error(e.getMessage(), e);
            throw new RemoteException(e.getMessage(), e);
        }
    }

    public String getMethod(String url) {
        OkHttpClient okHttpClient = new OkHttpClient().newBuilder()
                .connectTimeout(connectTimeOut, TimeUnit.SECONDS)
                .readTimeout(readTimeOut, TimeUnit.SECONDS).build();

        Request request = new Request.Builder().url(url).build();
        logger.info("getmethod url:" + url);
        Call call = okHttpClient.newCall(request);
        try {
            Response response = call.execute();
            String result = response.body().string();
            logger.info("getMethod result:" + result);
            return result;
        } catch (Exception e) {
            errLog.error(e.getMessage(), e);
            return null;
        }
    }

    public String postMethod(String url, Object obj) {
        OkHttpClient client = new OkHttpClient().newBuilder()
                .connectTimeout(connectTimeOut, TimeUnit.SECONDS)
                .readTimeout(readTimeOut, TimeUnit.SECONDS).build();
        try {
            logger.info("baseservice postmethod url:{},json:{}", url,
                    JsonUtils.toJsonString(obj));
            RequestBody body = RequestBody.create(JSON,
                    JsonUtils.toJsonString(obj));
            Request request = new Request.Builder().url(url).post(body).build();
            Response response = client.newCall(request).execute();
            String result = response.body().string();
            logger.info("postMethod result:" + result);
            return result;
        } catch (Exception e) {
            e.printStackTrace();
            errLog.error(e.getMessage(), e);
            return null;
        }
    }

    public <T> T parse(String response, Class<T> clazz) throws RemoteException {

        ObjectMapper mapper = new ObjectMapper();
        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);

        mapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
        mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
        mapper.configure(JsonParser.Feature.IGNORE_UNDEFINED, true);
        try {
            return (T) mapper.readValue(response, clazz);
        } catch (Exception e) {
            throw new RemoteException(e.getMessage(), e);
        }
        /*
         * try { return JsonUtils.toObject(response, clazz); } catch (Exception
         * e) { throw new RemoteException(e.getMessage(), e); }
         */

    }

}
